package ink.xiaobaibai.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ink.xiaobaibai.autoConfig.roleResources.ResourcesRoleMapping;
import ink.xiaobaibai.common.DeviceLogExcelBo;
import ink.xiaobaibai.common.DeviceLogReportForm;
import ink.xiaobaibai.common.MyPair;
import ink.xiaobaibai.common.MyRole;
import ink.xiaobaibai.entity.DeviceLog;
import ink.xiaobaibai.multipleClick.ForbidMultipleClick;
import ink.xiaobaibai.response.ResponseFormat;
import ink.xiaobaibai.service.IDeviceLogService;
import ink.xiaobaibai.service.IOxygenDeviceService;
import ink.xiaobaibai.service.IOzoneDeviceService;
import ink.xiaobaibai.serviceOxy.onePay.IUploadService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @description: 机器日志控制层
 * @author: 小白白
 * @create: 2021-05-28
 **/

@RestController
@RequestMapping("/log")
@Api(tags = "机器日志")
@CrossOrigin
@ResourcesRoleMapping(resourceName = "日志接口", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_REPORT})
@Slf4j
public class DeviceLogController {

    private static String baseUrl = null;

    static {
        try {
            baseUrl = new File(ResourceUtils.getURL("classpath:").getPath()).getParentFile().getParentFile().getParent().substring(5)
                    + File.separator + "tempExcel";
            File file = new File(baseUrl);
            if (!file.exists()) {
                boolean mkdirs = file.mkdirs();
                if (mkdirs) {
                    log.info("表格存储文件夹创建成功");
                }
            } else {
                log.info("表格存储文件夹已生成");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Autowired
    private IOzoneDeviceService ozoneDeviceService;

    @Autowired
    private IOxygenDeviceService oxygenDeviceService;

    @Autowired
    private IDeviceLogService deviceLogService;

    @Autowired
    private IUploadService uploadService;

    public static Set<MyPair<String, String>> fileUrlSet = new HashSet<>();

    private ExecutorService executorThreadPool = Executors.newFixedThreadPool(1);

    @GetMapping("/list")
    @ApiOperation("查看机器日志 | 页码+机器码+时间段")
    public ResponseFormat getDeviceLogList(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                           @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize,
                                           @RequestParam(value = "deviceCode", required = false) String deviceCode,
                                           @RequestParam(value = "startTime", required = false) Date startTime,
                                           @RequestParam(value = "endTime", required = false) Date endTime) {
        // 只有free机器的日志
        QueryWrapper<DeviceLog> q1 = new QueryWrapper<>();
        if (deviceCode != null) {
            q1.eq("device_code", deviceCode);
        }
        if (startTime != null && endTime != null) {
            q1.between("create_time", startTime, endTime);
        }
        Page<DeviceLog> page = this.deviceLogService.page(new Page<>(pageNum, pageSize), q1);
        return ResponseFormat.success(page);
    }

    /**
     * 为日志生成excel表格
     * 机器码+ 开始时间-结束时间  时间跨度不可超过31天即一个月
     */
    @PostMapping("/create-excel")
    @ApiOperation("将一段时间范围内的机器日志转为excel报表||根据机器码为某台机器生成日志excel表格,最长时间一个月")
    @ForbidMultipleClick(key = "#deviceLogExcelBo.deviceCode", prefixKey = "log-", durationSecondsTime = 60)
    public ResponseFormat createExcel(@RequestBody @Validated DeviceLogExcelBo deviceLogExcelBo) {


        Date startDate = deviceLogExcelBo.getStartDate();
        Date endDate = deviceLogExcelBo.getEndDate();
        if (startDate.getTime() >= endDate.getTime()) {
            return ResponseFormat.fail("请输入正确的时间范围");
        }
        if (DateUtils.addDays(startDate, 33).getTime() < endDate.getTime()) {
            return ResponseFormat.fail("单次生成最大区间为33天");
        }

        String deviceCode = deviceLogExcelBo.getDeviceCode();

        String fileName = "机器" + deviceCode + "日志" + DateFormatUtils.format(startDate, "yyyy-MM-dd") + "~" + DateFormatUtils.format(endDate, "yyyy-MM-dd") + ".xlsx";
        String filePath = baseUrl + "/" + fileName;

        if (fileUrlSet.contains(new MyPair<>(fileName, fileName))) {
            return ResponseFormat.fail("当前时间段已经创建过了,请在任务列表中查看");
        }

        QueryWrapper<DeviceLog> q1 = new QueryWrapper<>();
        q1.select("create_time");
        q1.eq("device_code", deviceCode);
        q1.between("create_time", startDate, endDate);
        List<DeviceLog> list = this.deviceLogService.list(q1);

        if (list.size() == 0) {
            return ResponseFormat.fail("本机器在当前时间范围内无日志");
        }

        this.executorThreadPool.execute(() -> {
            List<DeviceLogReportForm> deviceLogReportForms = list.stream().map(l -> new DeviceLogReportForm(l.getCreateTime())).collect(Collectors.toList());
            File file = new File(filePath);
            file.setExecutable(true);
            file.setReadable(true);
            file.setWritable(true);
            if (!file.exists()) {
                boolean mkdir = false;
                try {
                    mkdir = file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (mkdir) {
                    log.info("创建文件成功:" + filePath);
                } else {
                    log.error("创建文件失败:" + filePath);
                }
            }
            EasyExcel.write(filePath, DeviceLogReportForm.class).sheet("日志表").doWrite(deviceLogReportForms);
            String httpUrl = this.uploadFile(fileName);
            fileUrlSet.add(new MyPair<>(fileName, httpUrl));
        });

        return ResponseFormat.success("生成中");
    }

    @GetMapping("/log-cache")
    @ApiOperation("下载好的日志缓存集合")
    public ResponseFormat logCache() {
        return ResponseFormat.success(fileUrlSet);
    }

    @GetMapping("/log-url")
    @ApiOperation("获取文件下载地址")
    public ResponseFormat logUrl(@RequestParam("url") String url) {
        String privateUrl = this.uploadService.getPrivateUrl(url);
        return ResponseFormat.success(privateUrl);
    }

    private String uploadFile(String myFileName) {
        String filePath = baseUrl + "/" + myFileName;
        String httpUrl = this.uploadService.upload(filePath, myFileName);
        File file = new File(filePath);
        file.delete();
        return httpUrl;
    }

}
